package online.xuping.thousandsOfWorlds.common.importexcel;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.fastjson2.JSON;
import online.xuping.thousandsOfWorlds.common.constants.CommonErrorCodeEnum;
import online.xuping.thousandsOfWorlds.common.importexcel.domain.HeaderVO;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * EasyExcelUtil 类是 easyExcel工具类
 *
 * @author dongyinggang
 * @date 2022-02-09 20:09
 **/
@Slf4j
public class EasyExcelUtil {

    private static final String UTF_8 = "utf-8";

    /**
     * 插入头信息
     *
     * @param response 返回实体
     * @throws UnsupportedEncodingException 异常
     */
    public static void setResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding(UTF_8);
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        fileName = URLEncoder.encode(fileName, UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
    }


    /**
     * Excel导出
     *
     * @param response : 返回信息
     * @param list     : 导出的类表信息
     * @param clazz    : 类名
     * @author yujian
     * @date 2022/9/5 16:21
     **/
    public static void getExcel(HttpServletResponse response, List list, Class clazz) {
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding(UTF_8);
        response.setHeader("Content-disposition", "attachment;");
        try {
            EasyExcel.write(response.getOutputStream(), clazz)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet()
                    .doWrite(list);
        } catch (IOException e) {
            log.error("生成Excel失败，错误原因为：", e);
        }
    }


    /**
     * 捕获异常信息
     *
     * @param response 相应实体
     * @param e        异常实体
     */
    public static void exceptionInfo(HttpServletResponse response, Exception e) {
        // 重置response
        log.error("Excel下载失败", e);
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding(UTF_8);
        Map<String, String> map = new HashMap<>();
        map.put("status", "failure");
        map.put("message", "下载文件失败" + e.getMessage());
        try {
            response.getWriter().println(JSON.toJSONString(map));
        } catch (Exception err) {
            log.error("Excel下载失败", err);
        }
    }

    /**
     * resetResponse 方法是 重新设置返回内容
     *
     * @param response 返回响应
     * @param code     结果码
     * @param message  结果描述
     * @param result   结果值
     * @author dongyinggang
     * @date 2022/2/14 10:41
     */
    public static void resetResponse(ServletResponse response,
                                     String code,
                                     String message,
                                     Object result) {
        // 重置response
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding(UTF_8);
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("message", message);
        map.put("result", result != null ? JSON.toJSONString(result) : null);
        try {
            response.getWriter().println(JSON.toJSONString(map));
        } catch (Exception e) {
            log.error("设置返回值异常", e);
        }

    }

    /**
     * resetSuccessResponse 方法是 重新设置返回内容-正确
     *
     * @param response 返回响应
     * @author dongyinggang
     * @date 2022/2/14 10:41
     */
    public static void resetSuccessResponse(HttpServletResponse response) {
        resetResponse(response, CommonErrorCodeEnum.SUCCESS.getCode(), CommonErrorCodeEnum.SUCCESS.getMsg(), null);
    }

    /**
     * 获取导入类中属性标注的ExcelProperty注解的值
     *
     * @param clazz
     * @param <T>
     * @return excelHeadData
     * @author hongxing
     */
    public static <T> List<HeaderVO> excelHeadData(Class<T> clazz) {
        // 获取所有的私有属性
        Field[] fields = clazz.getDeclaredFields();
        // 遍历所有属性
        List<HeaderVO> excelHeadData = new ArrayList<>();
        for (Field field : fields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);

            excelHeadData.add(new HeaderVO(annotation.value()[0], annotation.value()[1]));
        }
        return excelHeadData;
    }

}
